Button
Communicate which actions are available and enable users to trigger them.
#Examples
Buttons are used in different contexts within the platform. To support this variety of use, the button component features properties to adjust its appearance and functionality. The most important properties are showcased here. They are split up into these categories:
- Variants. Use these to choose an overall visual style that matches the button’s purpose. In most cases, you'll need one of the regular variants. The call-to-action (CTA) variants are intended for marketing purposes within the platform.
- Visual. Use these to adjust certain visual characteristics. Specifically, the size of a button, the presence of an icon, the usage of HTML content, and presenting related buttons as a visually connected button group.
- State. Use these to enable a button’s disabled or loading state.
- Link. Use these to make a button behave like a link and (optionally) open in a new tab or window.
#Variants
#Regular
Use the variant
property when the default button implementation doesn't support your use case. Consult the table below to find out which button variant suits your use case:
Variant | Purpose | Usage guideline |
---|---|---|
Primary | Most important or frequently used action on a page. | Only use once per page (excluding overlays, such as modals or sidepanels). Not required on every page. |
Secondary | Alternative actions to a page's primary action. | Always place them directly next to a primary button. |
Default | Actions of regular importance. | Use when the action is neither primary or secondary in nature. Use when multiple destructive actions are needed on a page. |
Destructive | Actions that delete or remove data. | Only use once per page (excluding overlays, such as modals or sidepanels). Use default buttons if multiple destructive actions are needed on a page. |
Borderless | Less important or infrequently used actions. | Always use an icon, either with or without a label. |
<Button onClick={() => console.log("clicked")} variant="primary">
Primary
</Button>
<Button onClick={() => console.log("clicked")} variant="secondary">
Secondary
</Button>
<Button onClick={() => console.log("clicked")}>Default</Button>
<Button onClick={() => console.log("clicked")} variant="destructive">
Destructive
</Button>
<Button onClick={() => console.log("clicked")} variant="borderless">
<Icon>
<IconEdit />
</Icon>
Borderless
</Button>
#CTA
You can also use the variant
property to style the button component as call-to-action (CTA) buttons. Only use CTA buttons for marketing purposes, such as requesting a free trial.
There are three CTA button variants: primary, secondary and default. When you only need a single CTA button, choose the variant that is most visually appealing within its context of use. When using multiple adjacent CTA buttons, keep the following guidelines in mind:
- Use a different variant for each button.
- Use the primary variant for the most important or most frequently used action.
- Use the secondary variant for an action that serves as an alternative to the primary action.
- Always place the secondary variant directly next to the primary variant.
- Use the default variant for all other actions.
<Button onClick={() => console.log("clicked")} variant="ctaPrimary">
Primary
</Button>
<Button onClick={() => console.log("clicked")} variant="ctaSecondary">
Secondary
</Button>
<Button onClick={() => console.log("clicked")} variant="ctaDefault">
Default
</Button>
#Visual
#Size
Use the size
property to adjust a button's size. The default size is medium
and should be used in most cases. Use small
buttons when space is limited, such as in the Page Report. Use large
buttons for page level actions, such as exporting a page to HTML. Buttons placed next to each other should all have the same size.
<Button onClick={() => console.log("clicked")} size="small">
Small
</Button>
<Button onClick={() => console.log("clicked")}>Medium</Button>
<Button onClick={() => console.log("clicked")} size="large">
Large
</Button>
#Icon
To add an icon to a button, place an Icon component inside a button component, as shown in the example below. Visit the Icons Overview page for an overview of all available Fancy icons.
Place the icon before the label, to make it appear to the left of the label. Place the icon after the label, to make it appear to the right of the label. Only place an icon to the right of the label to signal directionality. This could, for instance, be a “next” button with a chevron pointing right.
Borderless buttons should always have an icon, whether it’s accompanied by a label or not. Other button variants should only include an icon to emphasize a button’s purpose. Don’t add an icon because of aesthetic reasons. When in doubt, don’t add an icon. People with visual impairments may not see the icon at all, so make sure the button’s (aria-)label makes the button’s purpose clear.
Use buttons that only contain an icon sparingly. Use them when space is limited or the button is repeated many times on a page. Also, the icon should be universally known, such as a pen for editing, a magnifying glass for searching, or a cogwheel for settings.
<Button onClick={() => console.log("clicked")}>
<Icon>
<IconEdit />
</Icon>
Edit item
</Button>
<Button onClick={() => console.log("clicked")}>
Next
<Icon rotation="270">
<IconChevron />
</Icon>
</Button>
<Button onClick={() => console.log("clicked")} aria-label="icon only button">
<Icon>
<IconSettings />
</Icon>
</Button>
<Button onClick={() => console.log("clicked")} aria-label="icon only button with fragment">
<>
<Icon>
<IconShare />
</Icon>
</>
</Button>
#HTML content
When adding a string or a number as a child to the Button component it will be wrapped in the InlineText component to get the proper font styling. When adding an Icon component or other HTML content as a child to the Button component it will not be wrapped in the InlineText component. To get the proper font styling when using HTML code around your string or number, you should wrap it in the InlineText component yourself.
<Button onClick={() => console.log("clicked")}>
<InlineText>
<span aria-hidden="true">HTML content</span>
<SrOnly>Reveal HTML content</SrOnly>
</InlineText>
</Button>
#Button group
When you have multiple buttons with similar functionality and equal importance, you can present them as a button group. To do this, place the buttons inside a <Button.Group>
component, as shown in the example below. Keep the following guidelines in mind, when using button groups:.
- Only put
default
variant buttons inside a button group. - Use the same size for every button in the button group.
- Either provide all or none of the buttons with an icon.
- Don't use button groups in tables. They provide a poor keyboard navigation experience.
<Button.Group aria-label="Descriptive title for the button group">
<Button>
<Icon>
<IconEdit />
</Icon>
Edit
</Button>
<Button>
<Icon>
<IconCopy />
</Icon>
Copy
</Button>
<Button>
<Icon>
<IconShare />
</Icon>
Share
</Button>
</Button.Group>
#State
#Loading
Buttons that trigger network operations should always enter a loading state when pressed. This is done by setting the button’s loading
property to true
. This state communicates to users that the button’s action is being processed. Buttons that don't trigger network operations should never enter a loading state, since their actions will be carried out immediately.
<Button onClick={() => console.log("clicked")} loading>
Save
</Button>
<Button onClick={() => console.log("clicked")} variant="ctaDefault" loading>
Save
</Button>
<Button onClick={() => console.log("clicked")} aria-label="Save" loading>
<Icon>
<IconSettings />
</Icon>
</Button>
#Disabled
To disable a button, set its disabled
property to true
. This state communicates to users that the button’s action is unavailable.
Use the disabled state sparingly. When you use it, make sure the rest of the page makes it clear why the action is unavailable and what is required to make it available. Try not to use this state for submit buttons in forms. It’s better to let users press the submit button, so the subsequent validation errors can explain, what exactly users need to do to proceed.
<Button onClick={() => console.log("clicked")} disabled>
Disabled
</Button>
<Button onClick={() => console.log("clicked")} variant="ctaDefault" disabled>
Disabled
</Button>
<Button onClick={() => console.log("clicked")} aria-label="icon only button" disabled>
<Icon>
<IconEdit />
</Icon>
</Button>
#Link
#Behave like a link
When a link answers the question “What can I do?”, rather than “Where can I go?”, it should look like a button. For example, you might have a link labelled "Add users”, which navigates users to the first page of an add-user flow. To users, that label makes it feel like they're triggering an action. To visually support this impression, the link should look like a button.
The button component’s href
property supports this use case. When set to a URL, the component's HTML tag will change from <button>
to <a>
. However, it will still look like a button.
<Button href="https://my2.siteimprove.com/Settings/Users/Create" variant="primary">
Add users
</Button>
#Open in new tab or window
When a button links to a page outside the Siteimprove Platform, it's generally best to open it in a new tab or window (depending on the user's browser setting). This can be achieved by setting the openNew
property to true
. Only use this property in combination with the href
property.
<Button
href="https://siteimprove.com/en/book-a-consultation/"
openNew={true}
variant="ctaPrimary"
>
Book a time to talk to us
</Button>
#Properties
#Button
Property | Description | Defined | Value |
---|---|---|---|
childrenOptional | element Text and icons to be displayed inside the button. | ||
onClickOptional | function Callback for onClick events | ||
typeOptional | "button" | "reset" | "submit" HTML attribute to define the type of the button - defaults to "button" | ||
hrefOptional | string URL to which the link will redirect (Should only be used for links that look like buttons) | ||
openNewOptional | boolean If set to true the link will be opened in a new tab (Should only be used for links that look like buttons) | ||
sizeOptional | "large" | "medium" | "small" Controls the size of the button - defaults to medium | ||
variantOptional | "borderless" | "ctaDefault" | "ctaPrimary" | "ctaSecondary" | "default" | "destructive" | "primary" | "secondary" How should the button look | ||
disabledOptional | boolean Can the button be clicked | ||
loadingOptional | boolean Should the button show a loading indicator | ||
idOptional | string Id applied to the button | ||
formOptional | string Id of a form element | ||
aria-pressedOptional | boolean Defines the button as a toggle button. The value of aria-pressed describes the state of the button | ||
aria-controlsOptional | string Identifies the element (or elements) whose contents or presence are controlled by the current element. | ||
aria-labelOptional | string Describe what happens if the button is clicked (for icon only buttons) | ||
aria-labelledbyOptional | string ID of an element that describes what happens if the button is clicked (for icon only buttons if aria-label is not set) | ||
aria-describedbyOptional | string IDs of the elements that describe the button's function | ||
aria-expandedOptional | boolean If the button controls a grouping of other elements, the aria-expanded state indicates whether the controlled grouping is currently expanded or collapsed. | ||
aria-haspopupOptional | "dialog" | "false" | "grid" | "listbox" | "menu" | "tree" | "true" If true, it indicates an interactive popup element, such as menu or dialog, is present | ||
boolean Indicates whether the element is exposed to an accessibility API. | |||
aria-roledescriptionOptional | string A description for the role of the button | ||
activeOptional | boolean Styles button as if it's in an active state | ||
inStaticModeOptional | "disable" | "hide" | "show" Specifies how button looks in the static mode. Defaults to `disable`, unless `href` is provided in which case it defaults to `show`. | ||
data-observe-keyOptional | string Unique string, used by external script e.g. for event tracking | ||
classNameOptional | string Custom className that's applied to the outermost element (only intended for special cases) | ||
styleOptional | object Style object to apply custom inline styles (only intended for special cases) | ||
tabIndexOptional | number Tab index of the outermost HTML element of the component | ||
onKeyDownOptional | function Callback for onKeyDown event | ||
onMouseDownOptional | function Callback for onMouseDown event | ||
onMouseEnterOptional | function Callback for onMouseEnter event | ||
onMouseLeaveOptional | function Callback for onMouseLeave event | ||
onFocusOptional | function Callback for onFocus event | ||
onBlurOptional | function Callback for onBlur event |
#Button.Group
Property | Description | Defined | Value |
---|---|---|---|
childrenOptional | element Must be Button components. | ||
aria-labelOptional | string A descriptive title for the button group | ||
data-observe-keyOptional | string Unique string, used by external script e.g. for event tracking | ||
classNameOptional | string Custom className that's applied to the outermost element (only intended for special cases) | ||
styleOptional | object Style object to apply custom inline styles (only intended for special cases) |
#Guidelines
#Best practices
#Do not use when
#Accessibility
Explore detailed guidelines for this component: Accessibility Specifications
#Writing
#Notable changes
#Version 0.0.x
- There used to be a separate property for turning a default button into a CTA button. Now, the variant property also includes CTA button variants.
- The
IconOnlyButton
component has been deprecated. Now, you create a button only containing an icon by placing an icon component inside aButton
compoment. - The
LinkButton
component has been deprecated. This component looked like a button, but behaved like a link. Now, you achieve the same result by using theButton
component and providing itshref
property with a URL.